Why do many Americans perceive the U.S. economy as struggling, even when macroeconomic indicators suggest otherwise?¶

Table of Contents¶

  • Data collection
  • Data Exploration
  • Data Cleaning
  • Data and Graph Preparation
  • Introduction
  • Visualization and Analysis
  • Considerations For Further Insight
In [1]:
from fredapi import Fred
from requests import get
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import plotly.express as px

Data collection¶

In [2]:
Gallup_df=pd.read_csv('data-y7uQi.csv')
Gallup_df.head()
Out[2]:
X.1 Index
0 Jan 1 1996 1
1 Jul 1 1996 13
2 Aug 1 1996 18
3 Oct 1 1996 23
4 Jan 1 1997 17
In [38]:
Gallup_df2=pd.read_csv('data-Yv6Vx.csv')
Gallup_df2.head()
Out[38]:
X.1 Getting better Getting worse Same (vol.) No opinion
0 2024 Dec 2 38 52 7 3
1 2024 Nov 6 36 55 5 4
2 2024 Oct 1 32 62 4 2
3 2024 Sep 3 32 62 5 2
4 2024 Aug 1 31 63 3 2
In [24]:
fred = Fred(api_key='e7adfc69642678c50ce3c1126d8e3f3d')
series_list = {
    "NGDPSAXDCUSQ": "Nominal GDP",
    "FEDFUNDS": "Interest Rates",
    "CPIAUCSL": "CPI(Inflation)",
    "UNRATE": "Unemployment Rate",
    "SPCS20RSA":"Home Price Index",
    "CES0500000003":"Average Hourly Earnings",
    "CPIUFDNS":"Cost of living Index"}
data = {}
for series_id, column_name in series_list.items():
    data[column_name] = fred.get_series(series_id)
Fred_Data = pd.DataFrame(data)
Fred_Data.head()
Out[24]:
Nominal GDP Interest Rates CPI(Inflation) Unemployment Rate Home Price Index Average Hourly Earnings Cost of living Index
1913-01-01 NaN NaN NaN NaN NaN NaN 9.7
1913-02-01 NaN NaN NaN NaN NaN NaN 9.6
1913-03-01 NaN NaN NaN NaN NaN NaN 9.6
1913-04-01 NaN NaN NaN NaN NaN NaN 9.7
1913-05-01 NaN NaN NaN NaN NaN NaN 9.6

Data Exploration¶

In [5]:
Gallup_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 252 entries, 0 to 251
Data columns (total 2 columns):
 #   Column  Non-Null Count  Dtype 
---  ------  --------------  ----- 
 0   X.1     252 non-null    object
 1   Index   252 non-null    int64 
dtypes: int64(1), object(1)
memory usage: 4.1+ KB
In [6]:
Gallup_df.describe() 
Out[6]:
Index
count 252.000000
mean -4.519841
std 25.956975
min -72.000000
25% -21.000000
50% -5.000000
75% 14.250000
max 56.000000

Observations¶

  • Gallup_df
    • The 'X.1' column containing the dates is a Dtype object.
    • Date is not the index.
    • The data itself is clean.
In [ ]:
Gallup_df2.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 85 entries, 0 to 84
Data columns (total 5 columns):
 #   Column          Non-Null Count  Dtype 
---  ------          --------------  ----- 
 0   X.1             85 non-null     object
 1   Getting better  85 non-null     int64 
 2   Getting worse   85 non-null     int64 
 3   Same (vol.)     85 non-null     int64 
 4   No opinion      85 non-null     object
dtypes: int64(3), object(2)
memory usage: 3.4+ KB
In [25]:
Gallup_df2.describe() 
Out[25]:
Getting better Getting worse Same (vol.)
count 85.000000 85.000000 85.000000
mean 36.800000 57.341176 4.494118
std 12.836703 13.986859 1.452613
min 13.000000 33.000000 1.000000
25% 26.000000 45.000000 3.000000
50% 33.000000 61.000000 5.000000
75% 49.000000 69.000000 5.000000
max 61.000000 85.000000 9.000000

Observations¶

  • Gallup_df2
    • The 'X.1' column containing the dates is a Dtype object.
    • Date is not the index.
    • The 'No opinion'is a Dtype object and not a useable integer.
In [26]:
Fred_Data.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 1345 entries, 1913-01-01 to 2025-01-01
Freq: MS
Data columns (total 7 columns):
 #   Column                   Non-Null Count  Dtype  
---  ------                   --------------  -----  
 0   Nominal GDP              299 non-null    float64
 1   Interest Rates           847 non-null    float64
 2   CPI(Inflation)           936 non-null    float64
 3   Unemployment Rate        925 non-null    float64
 4   Home Price Index         299 non-null    float64
 5   Average Hourly Earnings  227 non-null    float64
 6   Cost of living Index     1344 non-null   float64
dtypes: float64(7)
memory usage: 84.1 KB
In [27]:
Fred_Data.describe() 
Out[27]:
Nominal GDP Interest Rates CPI(Inflation) Unemployment Rate Home Price Index Average Hourly Earnings Cost of living Index
count 2.990000e+02 847.000000 936.000000 925.000000 299.000000 227.000000 1344.000000
mean 1.916354e+06 4.609020 121.519631 5.681622 189.786853 26.174626 90.110816
std 1.925671e+06 3.565496 87.094194 1.708949 58.904567 4.307423 89.143996
min 7.020700e+04 0.050000 21.480000 2.500000 100.589697 20.050000 9.400000
25% 2.398569e+05 1.825000 32.432500 4.400000 144.313548 22.750000 17.000000
50% 1.201540e+06 4.290000 109.000000 5.500000 178.839344 25.090000 36.000000
75% 3.365420e+06 6.155000 194.000000 6.700000 212.618196 29.385000 156.350000
max 7.343728e+06 19.100000 317.685000 14.800000 335.827481 35.870000 333.566000

Observations¶

  • The fred Data
    • The frequency of each data point over time varys for each column.
    • The count for each variable is diffrent, that means there is a good amount of missing data we need to remove.
    • The data also goes back all the way to 1913 for some variables.
    • The date was already in datetime and also set as the index.

Data Cleaning¶

In [13]:
# changing column type to date
Gallup_df['X.1']=pd.to_datetime(Gallup_df['X.1'])

# Setting Date as the index for the DF
Gallup_df.set_index('X.1', inplace=True)
Gallup_df.index.name = 'Date'
Gallup_df.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 252 entries, 1996-01-01 to 2024-12-02
Data columns (total 1 columns):
 #   Column  Non-Null Count  Dtype
---  ------  --------------  -----
 0   Index   252 non-null    int64
dtypes: int64(1)
memory usage: 3.9 KB

Cleaning¶

  • Gallup_df
    • Changed date column into datetime.
    • Made date column the index.
In [35]:
# changing column type to date
Gallup_df2['X.1']=pd.to_datetime(Gallup_df2['X.1'])

# Setting Date as the index for the DF
Gallup_df2.set_index('X.1', inplace=True)
Gallup_df2.index.name = 'Date'

# Droping 'No Opinon' column because it had a lot of null and missing data. Was also irrelevant for analysis.
Gallup_df2=Gallup_df2.drop('No opinion',axis=1)
Gallup_df2.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 85 entries, 2024-12-02 to 2018-01-02
Data columns (total 3 columns):
 #   Column          Non-Null Count  Dtype
---  ------          --------------  -----
 0   Getting better  85 non-null     int64
 1   Getting worse   85 non-null     int64
 2   Same (vol.)     85 non-null     int64
dtypes: int64(3)
memory usage: 2.7 KB

Cleaning¶

  • Gallup_df2
    • Changed date column into datetime.
    • Made date column the index.
    • removed "No opinion" column because of missing data and it's irrelevance to the analysis.
In [28]:
#droping all rows with missing data.
df=Fred_Data.dropna()
df.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 74 entries, 2006-04-01 to 2024-07-01
Freq: 3MS
Data columns (total 7 columns):
 #   Column                   Non-Null Count  Dtype  
---  ------                   --------------  -----  
 0   Nominal GDP              74 non-null     float64
 1   Interest Rates           74 non-null     float64
 2   CPI(Inflation)           74 non-null     float64
 3   Unemployment Rate        74 non-null     float64
 4   Home Price Index         74 non-null     float64
 5   Average Hourly Earnings  74 non-null     float64
 6   Cost of living Index     74 non-null     float64
dtypes: float64(7)
memory usage: 4.6 KB
In [36]:
df.describe()
Out[36]:
Nominal GDP Interest Rates CPI(Inflation) Unemployment Rate Home Price Index Average Hourly Earnings Cost of living Index
count 7.400000e+01 74.000000 74.000000 74.000000 74.000000 74.000000 74.000000
mean 4.796686e+06 1.526892 243.887284 5.954054 203.355096 25.970270 249.272905
std 1.109052e+06 1.931459 29.979955 2.314764 56.526588 4.138085 35.365768
min 3.438356e+06 0.050000 200.700000 3.400000 137.146012 20.150000 193.700000
25% 3.829992e+06 0.110000 219.573000 4.050000 157.123970 22.772500 221.190000
50% 4.585176e+06 0.335000 237.575000 5.000000 193.155014 24.950000 246.770500
75% 5.427254e+06 2.370000 256.897750 7.750000 220.776602 28.380000 260.700750
max 7.343728e+06 5.330000 313.534000 14.800000 331.287120 35.070000 330.561000

Cleaning¶

  • Fred Data
    • Droped all rows with missing data and values.
      • Made every column have the save frequency.
      • Every column is the same hight with 74 observations each.
      • The data starts from 2006 now.
      • trimed down the data leaving the data clean and with enough to run our analysis.

Data and Graph Preparation¶

In [14]:
# Cutting off data at 2015 and up.
Gallup_df= Gallup_df[Gallup_df.index>='2015-01-01']
Gallup_df.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 88 entries, 2015-01-01 to 2024-12-02
Data columns (total 1 columns):
 #   Column  Non-Null Count  Dtype
---  ------  --------------  -----
 0   Index   88 non-null     int64
dtypes: int64(1)
memory usage: 1.4 KB
In [43]:
Gallup_df2.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 85 entries, 2024-12-02 to 2018-01-02
Data columns (total 3 columns):
 #   Column          Non-Null Count  Dtype
---  ------          --------------  -----
 0   Getting better  85 non-null     int64
 1   Getting worse   85 non-null     int64
 2   Same (vol.)     85 non-null     int64
dtypes: int64(3)
memory usage: 2.7 KB
In [42]:
# Cutting off data at 2015 and up.
df = df[df.index >= '2015-01-01']

# Creating new Rate of change columns.
df['GDP Rate (%)'] = df['Nominal GDP'].pct_change()*100
df['Inflation Rate (%)'] = df['CPI(Inflation)'].pct_change()*100
df['Home Price Rate(%)']=df['Home Price Index'].pct_change()*100
df['Cost of living Rate(%)']=df['Cost of living Index'].pct_change()*100
df['Wage Growth Rate(%)']=df['Average Hourly Earnings'].pct_change()*100
df.info()
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 39 entries, 2015-01-01 to 2024-07-01
Freq: 3MS
Data columns (total 12 columns):
 #   Column                   Non-Null Count  Dtype  
---  ------                   --------------  -----  
 0   Nominal GDP              39 non-null     float64
 1   Interest Rates           39 non-null     float64
 2   CPI(Inflation)           39 non-null     float64
 3   Unemployment Rate        39 non-null     float64
 4   Home Price Index         39 non-null     float64
 5   Average Hourly Earnings  39 non-null     float64
 6   Cost of living Index     39 non-null     float64
 7   GDP Rate (%)             38 non-null     float64
 8   Inflation Rate (%)       38 non-null     float64
 9   Home Price Rate(%)       38 non-null     float64
 10  Cost of living Rate(%)   38 non-null     float64
 11  Wage Growth Rate(%)      38 non-null     float64
dtypes: float64(12)
memory usage: 4.0 KB

Alterations¶

  • Gallup_df
    • set the df to only show 2015 and older as we no not need anything befor that for our analysis.
  • Gallup_df2
    • The data already started from 2018. No chages.
  • Fred Data
    • Cut out everything that was befor 2015
    • Created a new column to extract the rate of change from previous to current observations.
In [47]:
# Final data
Gallup_df.head()
Out[47]:
Index
Date
2015-01-01 7
2016-01-01 -9
2017-01-01 23
2017-12-01 13
2018-01-01 18
In [48]:
# Final data
Gallup_df2.head()
Out[48]:
Getting better Getting worse Same (vol.)
Date
2024-12-02 38 52 7
2024-11-06 36 55 5
2024-10-01 32 62 4
2024-09-03 32 62 5
2024-08-01 31 63 3
In [50]:
# Final data
df.head()
Out[50]:
Nominal GDP Interest Rates CPI(Inflation) Unemployment Rate Home Price Index Average Hourly Earnings Cost of living Index GDP Rate (%) Inflation Rate (%) Home Price Rate(%) Cost of living Rate(%) Wage Growth Rate(%)
2015-01-01 4515882.5 0.11 234.747 5.7 175.047514 24.75 246.538 NaN NaN NaN NaN NaN
2015-04-01 4569946.0 0.12 236.222 5.4 177.710269 24.89 246.121 1.197186 0.628336 1.521161 -0.169142 0.565657
2015-07-01 4600406.5 0.13 238.034 5.2 179.388543 25.01 247.003 0.666540 0.767075 0.944388 0.358360 0.482121
2015-10-01 4608784.5 0.12 237.733 5.0 181.921952 25.20 249.052 0.182114 -0.126453 1.412247 0.829545 0.759696
2016-01-01 4631483.5 0.34 237.652 4.8 184.681531 25.37 248.631 0.492516 -0.034072 1.516903 -0.169041 0.674603
In [52]:
#visualizations

#visualization (graphing gallup poll on economic confidence index)
fig_1=px.line(Gallup_df,range_y=[-60,50], width=1000, height=500, 
              title='FIGURE #1<br>Gallup Economic Confidence Index, 2015-2024<br><sup>Among U.S. adults')
fig_1.add_vline(x='2020-01-01', line_color="brown",line_dash="dot")
fig_1.add_annotation(text="Covid-19", x='2019-09-01',y=10,font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False,
                     hovertext='The outbreak of the COVID-19 global pandemic and the subsequent lockdowns')

#visualization (graphing gallup poll on economic outlook)
fig_2=px.line(Gallup_df2, y=Gallup_df2.columns[0:], height=500,
        title='FIGURE #2<br>Economic Confidence -- Economic Outlook,2018-2024<br><sup>Right now, do you think that economic conditions in the country as a whole are getting better or getting worse?')
fig_2.add_vline(x='2020-01-01', line_color="brown",line_dash="dot")
fig_2.add_annotation(text="Covid-19", x='2019-10-01',y=80, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False,
                     hovertext='The outbreak of the COVID-19 global pandemic and the subsequent lockdowns')

#visualization (graphing Domestic GDP)
fig_3=px.line(df, y=['Nominal GDP'],width=900, height=600,
              title= 'FIGURE #3<br>Nominal Gross Domestic Product for United States, 2015-2024<br><sup>FRED Series ID:(NGDPSAXDCUSQ)')
fig_3.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_3.add_annotation(text="Covid-19", x='2019-09-01',y=6500000, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_3.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_3.add_annotation(text="Intrest Rate Hikes", x='2022-03-01',y=7000000, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)

#visualization (graphing rate of change for GDP)
fig_3A=px.line(df, y=['GDP Rate (%)'],width=900, height=600,
              title= 'FIGURE #3A<br>GDP Growth Rate, 2015-2024<br><sup>Percent Change in GDP from previous observation to current')
fig_3A.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_3A.add_annotation(text="Covid-19", x='2019-09-01',y=5, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_3A.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_3A.add_annotation(text="Intrest Rate Hikes", x='2022-03-01',y=7, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)

#visualization (graphing Iinterest rates)
fig_4=px.line(df, y='Interest Rates', width=900, height=600,
              title= 'FIGURE #4<br>Federal Funds Effective Rate (Interest Rate), 2015-2024 <br><sup>FRED Series ID:(FEDFUNDS)')
fig_4.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_4.add_annotation(text="Covid-19", x='2019-09-01',y=4.5, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_4.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_4.add_annotation(text="Intrest Rate Hikes", x='2022-03-01',y=4.5, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)

#visualization (graphing Consumer price index)
fig_5=px.line(df, y='CPI(Inflation)',width=900, height=600,
              title= 'FIGURE #5<br>Consumer Price Index for All Urban Consumers (Inflation), 2015-2024 <br><sup>FRED Series ID:(CPIAUCSL)')
fig_5.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_5.add_annotation(text="Covid-19", x='2019-09-01',y=290, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_5.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_5.add_annotation(text="Intrest Rate Hikes", x='2022-03-01',y=300, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)

#visualization (graphing Rate of change for CPI(inflation))
fig_6=px.line(df, y='Inflation Rate (%)', width=900, height=600,
              title= 'FIGURE #6<br>Rate of Inflation, 2015-2024 <br><sup>Percent Change in CPI from previous observation to current.')
fig_6.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_6.add_annotation(text="Covid-19", x='2019-09-01',y=1.5, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_6.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_6.add_annotation(text="Intrest Rate Hikes", x='2022-03-01',y=.5, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)

#visualization (graphing unemployment rate)
fig_7=px.line(df, y='Unemployment Rate', width=900, height=600,
              title= 'FIGURE #7<br>Unemployment Rate, 2015-2024 <br><sup>FRED Series ID:(UNRATE)')
fig_7.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_7.add_annotation(text="Covid-19", x='2019-09-01',y=12, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_7.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_7.add_annotation(text="Intrest Rate Hikes", x='2022-03-01',y=10, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)

#visualization (graphing home price index)
fig_8=px.line(df, y='Home Price Index',width=900, height=600,
              title= 'FIGURE #8<br>S&P CoreLogic Case-Shiller 20-City Composite Home Price Index(Home price Index), 2015-2024<br><sup>FRED Series ID:(SPCS20RSA)')
fig_8.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_8.add_annotation(text="Covid-19", x='2019-09-01',y=300, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_8.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_8.add_annotation(text="Intrest Rate Hikes", x='2022-03-01',y=250, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)

#visualization (graphing cost of living: food)
fig_9=px.line(df,y='Cost of living Index', width=900, height=600,
              title= 'FIGURE #9<br>Consumer Price Index for All Urban Consumers(Cost of living Index: Food Prices), 2015-2024<br><sup>FRED Series ID:(CPIUFDNS)')
fig_9.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_9.add_annotation(text="Covid-19", x='2019-09-01',y=300, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_9.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_9.add_annotation(text="Intrest Rate Hikes", x='2022-03-01',y=270, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)

#visualization (graphing Wage Growth)
fig_10=px.line(df,y='Average Hourly Earnings',width=900, height=600,
               title= 'FIGURE #10<br>Average Hourly Earnings of All Employees(Wage Growth), 2015-2024 <br><sup>FRED Series ID:(CES0500000003)')
fig_10.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_10.add_annotation(text="Covid-19", x='2019-09-01',y=33, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_10.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_10.add_annotation(text="Intrest Rate Hikes", x='2022-03-01',y=30, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)

#visualization (graphing rate of change for home prices, cost of living, wage growth)
fig_11=px.line(df[df.index>= '2018-01-01'],y=['Home Price Rate(%)','Cost of living Rate(%)','Wage Growth Rate(%)'],width=1000, height=500, 
               title='FIGURE #11<br>Rate of change for Home Prices, Cost of Living, and Wage Growth,2019-2024<br><sup>Percent Change in Wage Growth, Cost of living Index, and Home price Index from previous observation to current')
fig_11.add_vline(x='2020-01-01',line_color="brown",line_dash="dot")
fig_11.add_annotation(text="Covid-19", x='2019-09-01',y=5, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
fig_11.add_vline(x='2022-03-01',line_color="green",line_dash="dot")
fig_11.add_annotation(text="Intrest Rate Hikes", x='2021-09-01',y=-1, font=dict(size=10, color="brown"),bgcolor='wheat',showarrow=False)
print('')

Graphing¶

  • Economic indicators over time, and rate of change for economic incicators over time.
    • Along with descriptive titles of said Indicators.
    • More common and simpler titles if needed.
    • Citations of the series ID
    • virtical lines and annotations indicating significant and relevant events.

Introduction¶

The U.S. economy has undergone significant fluctuations over the past four to five years, shaped by the COVID-19 pandemic, government intervention, and subsequent economic adjustments. While macroeconomic indicators such as GDP growth, unemployment rates, and inflation provide a structured narrative of crisis, recovery, and stabilization, public perception has often diverged from these trends. Despite expert assessments suggesting a strong economic rebound, consumer confidence has remained historically low.

This analysis explores the disconnect between economic data and public sentiment by examining key macroeconomic indicators alongside survey data. Using data from the Federal Reserve Economic Data (FRED) database and Gallup polls, we assess why many Americans continue to feel pessimistic about the economy, even as traditional economic metrics suggest improvement.

Visualization & Analysis¶

When looking from an expert's perspective and at macroeconomic figures, we see a certain narrative about the past four to five years. During early 2020 (marked by the brown dotted line), the global outbreak of COVID and subsequent lockdowns had a significant impact. Unemployment rates skyrocketed, reaching a high of 14% in April 2020 (FIGURE #7). Economic activity came to a halt, causing GDP to decline for the first time since 2008, contracting by 8.34% between January 2020 and April 2020 (FIGURES #3 & #3A). Due to the lack of demand, prices fell, leading to deflation, with inflation decreasing by 1.07% in April 2020 (FIGURE #6). In response, the Federal Reserve cut interest rates to stimulate economic activity, lowering them to 0.5% in April 2020 (FIGURE #4). However, the only way to jump-start an economy in this condition was through massive stimulus. The U.S. government printed a vast amount of money and increased the money supply, subsidizing almost every aspect of the economy.

However, such drastic actions had consequences. The large influx of cash that kept the economy from collapsing also caused the post-lockdown economy to overheat. We see both the CPI and inflation rates surge, rising from a monthly rate of -1.07% in April 2020 to 2.25% in April 2022 (FIGURES #5 & #6). During this period (between the brown and green lines), unemployment dropped to near record lows of 3.5% in 2022, near-zero interest rates fueled GDP growth by 8.77% between its low in April 2020 and July 2020 (FIGURE #3), and alongside these developments, inflation became uncontrolled.

At this point, the nation had overcome the challenge of restarting the economy but now faced an overheated economy. To slow down this runaway economic surge, the Federal Reserve raised interest rates (marked by the green dotted line) from 0.08% at the beginning of 2022 to 4.33% by the end of the year, eventually peaking at 5.33% in October 2023 (FIGURE #4). These record-high interest rates were effective. Inflation gradually declined closer to its natural rate, falling from a monthly rate of 2.25% in April 2022 to 0.83% in January 2023 (FIGURE #6). Additionally, the Fed managed a "soft landing"—cooling down the economy without triggering a recession. GDP continued to grow at a monthly rate of around 2% from October 2020 to the present (FIGURES #3 & #3A), unemployment remained low at approximately 3.7% (FIGURE #7), and soon, interest rates are expected to return to historical norms. For economists and world leaders, this is considered a successful outcome. From the chaos of the COVID lockdowns to an overheated economy, the U.S. emerged in relatively strong shape, with low unemployment and record-high GDP growth. The same cannot be said for many European countries, which continue to struggle with uncontrolled inflation and mild recessions. This is the mainstream narrative among experts, and while it is not entirely incorrect, it omits critical details.

In [18]:
fig_3.show()
fig_3A.show()
fig_4.show()
fig_5.show()
fig_6.show()
fig_7.show()

Although headline macroeconomic figures and expert analyses suggest that the U.S. has largely recovered from the global economic shocks of the COVID pandemic, public sentiment tells a different story. According to a Gallup public opinion poll on the economic confidence index, public confidence in the economy dropped from 41 points in February 2020 to -22 in April 2020. This sentiment remained around an average index value of -10 points until the end of 2021. However, by June 2022—when most other economic indicators suggested recovery and stabilization—the public economic confidence index fell to a new low of -55 points. This pessimism persisted, averaging around -30 points through the end of 2024 (FIGURE #1).

Another Gallup poll on economic confidence outlook, which measures whether people expect the economy to improve or worsen, further supports this negative sentiment. In February 2020, 61% of Americans expected the economy to improve, while 33% expected it to worsen, with 5% believing it would stay the same. By April 2020, those figures had reversed, with only 22% expecting improvement and 74% expecting worsening conditions. While sentiment improved slightly over time—reaching its most optimistic point in April 2021 with 47% expecting improvement and 46% expecting deterioration—this trend reversed. By June 2022, economic outlook reached its most pessimistic point, with 85% expecting worsening conditions and only 13% expecting improvement. These sentiments have remained largely negative, with an average of 68% expecting worse economic conditions and only 25% expecting improvement (FIGURE #2). This widespread pessimism contrasts sharply with expert opinions and macroeconomic indicators and played a decisive role in the 2024 election outcome.

In [19]:
fig_1.show()
fig_2.show()

A significant portion of this disconnect in public opinion can be attributed to the widening gap between the cost of living and real wages. The cost of living can be divided into short-term, day-to-day expenses and long-term financial commitments and investments. To represent short-term costs, we look at food prices using the Consumer Price Index for All Urban Consumers (FIGURE #9), and for long-term costs, we examine home prices using the Composite Home Price Index (FIGURE #8). To capture wages, we analyze Average Hourly Earnings of All Employees (FIGURE #10). Examining the growth rates of these three indices before 2020, they remained relatively close, growing at a monthly rate between 0% and 1.3% (FIGURE #11). However, post-2020, these growth rates diverged significantly.

Initially, wages experienced a dramatic increase, from a monthly growth rate of 0.74% in January 2020 to 5.52% in April 2020 (FIGURE #11), driven by government stimulus checks and the Paycheck Protection Program (PPP), which allowed employers to continue paying workers. However, this wage growth was short-lived. Once the first wave of stimulus ended, wages declined sharply, with growth rates falling from 5.52% in April 2020 to -2.09% in July 2020 (FIGURE #11), erasing most of the gains. Wage growth then stabilized at 0.54% in October 2020 and remained around 1% for the next 3–4 years, showing no significant improvement (FIGURE #11).

The cost of living, however, followed a different trajectory. Food prices initially spiked due to increased demand and supply chain disruptions, with growth rates rising from 0.54% in January to 2.18% in April 2020 (FIGURE #11). After this spike, food price growth declined to 0.78% in July, hitting a low of 0.35% in October 2020 (FIGURE #11). However, unlike wages, which saw negative growth, food prices never reversed to undo their increase. After October 2020, food price growth steadily rose, peaking at 3.28% in July 2022. From April 2021 to January 2023, food prices grew at an average rate of 2.3%, compared to an average wage growth rate of around 1% during the same period (FIGURE #11). Since January 2023, food prices have continued growing at a rate similar to wages.

For long-term living costs, the disparity is even starker. In July 2020, home prices skyrocketed, with growth rates jumping from 0.91% monthly in July 2020 to 5.18% in October 2020. Over the next two years, home prices continued growing at around 5% monthly until April 2022 (FIGURE #11), leading to an almost 40% increase in home prices nationwide (FIGURE #8). This surge also drove up rents and housing costs across the board. While home price growth slowed, dropping to -2.29% in October 2022 and stabilizing at 2.24% in July 2023 (FIGURE #11), this decrease was not nearly enough to offset the massive price hikes of the previous two years.

The growing disconnect between wage stagnation and skyrocketing living costs explains why so many people perceive the economy as being in crisis. Over the past four to five years, while inflation and living costs surged and remained high, wages failed to keep pace. Experts may declare inflation "solved" now that growth rates have stabilized, but they overlook the immense gap created between wages and living costs. This gap and its impact on quality of life are the primary reasons behind the disconnect in public sentiment.

In [53]:
fig_8.show()
fig_9.show()
fig_10.show()
fig_11.show()

Considerations For Further Insight.¶

The research and analysis presented in this project provide only a surface-level exploration of the disconnect between macroeconomic indicators and public sentiment. Due to the scope and limitations of this research project, several factors that may contribute to this disparity remain unexplored. A more comprehensive analysis would require a deeper investigation into additional factors that shape public perception and economic performance. Below are key research questions to consider for gaining a fuller understanding of this issue.

GDP Growth and Distribution¶

  • How has GDP growth been distributed across its four components: investment, government spending, consumption, and net exports?
  • What specific expenses comprise consumption, and how have American spending habits changed over time?

Employment and Labor Market Trends¶

  • How do unemployment rates vary by industry compared to the aggregate national rate?
  • Which types of jobs are in high demand, and which occupations are in decline?
  • What are the trends in underemployment? Are more workers overqualified for their jobs, or are they fully utilizing their skills and education?

Household Debt and Financial Strain¶

  • How has the level of household debt evolved in recent years? Are more Americans taking on unsustainable debt?
  • What are the primary components of household debt, and what forms does American debt take (e.g., mortgages, credit cards, student loans)?
  • Is the debt-driven economy increasingly extracting value from financially vulnerable individuals, making long-term economic stability unsustainable?

Inflation and Purchasing Power¶

  • How has inflation affected goods at different price points? Are lower-cost essentials rising in price faster than higher-cost items?
  • How does this trend impact different socioeconomic groups, particularly low-income households?

Wealth Distribution and Inequality¶

  • How have inequality indicators, such as the Gini coefficient, evolved in recent years?
  • Is there a growing disconnect between the nation’s overall wealth and the financial well-being of the average American?